package com.culturalCenter.dataCenter.globalconfig.filter;

import cn.hutool.crypto.digest.DigestUtil;
import com.culturalCenter.dataCenter.Utils.ApiResult;
import com.culturalCenter.dataCenter.Utils.ResultCode;
import com.culturalCenter.dataCenter.constant.AuthConstants;
import com.culturalCenter.dataCenter.entity.sysauth.SystemAuth;
import com.culturalCenter.dataCenter.mapper.sysauth.SystemAuthMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Objects;

/**
 * @Author zhao
 * @Date 2021-10-16 10:41
 */
@Component
@Slf4j
public class CustomHeaderFilter implements Filter {

    @Autowired
    private SystemAuthMapper systemAuthMapper;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        // 跨域处理
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
        // 验证头部信息
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String questUrl = request.getServletPath();
        // swagger-ui页面和车流接口地址免验证
        if (questUrl.contains("/swagger")
//                || questUrl.contains("/v2/api-docs")
                || questUrl.contains("/webjars")
                || questUrl.contains("/doc.html")
                || questUrl.contains("/parking")
                || questUrl.contains("/user/analysis")
                || questUrl.contains("/passengerflow")
                || questUrl.contains("/v1/training/table")
                || questUrl.contains("/v1/training/resourceDistributionTable")
                || questUrl.contains("/v1/training/latestResourceRecommend")
                || questUrl.contains("/weather/getWeather")
                || questUrl.contains("/v1/monitor/weather")
                || questUrl.contains("/v1/sms/sendMsg")
                || questUrl.contains("/activity/informationScreen/site")){
            FilterInvocation fi = new FilterInvocation(request, httpServletResponse, filterChain);
            // 执行下一个过滤器
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } else {
            boolean validatePass = validateHeaderAuth(request);
            if (!validatePass) {
                RelstResponse(httpServletResponse, ApiResult.instance(ResultCode.HEAD_NEEDED));
                return;
            }
            FilterInvocation fi = new FilterInvocation(request, httpServletResponse, filterChain);
            // 执行下一个过滤器
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        }
    }

    private void RelstResponse(HttpServletResponse response, ApiResult result) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        response.setStatus(200);
        ObjectMapper om = new ObjectMapper();
        out.write(om.writeValueAsString(result));
        out.flush();
        out.close();
    }

    /**
     * 校验请求头 acc_xx
     */
    private boolean validateHeaderAuth(HttpServletRequest request) {
        try {
            String appId = request.getHeader(AuthConstants.ACC_APPID);
            String appKey = request.getHeader(AuthConstants.ACC_APPKEY);
            String timestamp = request.getHeader(AuthConstants.ACC_TIMES);
            String token = request.getHeader(AuthConstants.ACC_TOKEN);
            long currentTimeMillis = System.currentTimeMillis();
            long times = AuthConstants.REQUEST_TTL;
            if (Objects.isNull(timestamp) || (currentTimeMillis - Long.parseLong(timestamp) > times)) {
                // 请求超时
                return false;
            }

            SystemAuth systemAuth = systemAuthMapper.queryByAppId(appId, appKey);
            if (Objects.isNull(systemAuth)) {
                // 此appid不存在系统中，直接返回验证失败
                log.warn("appid: {} 不存在在系统中", appId);
                return false;
            }
            String md5Hex = DigestUtil.md5Hex(systemAuth.getAppkey() + systemAuth.getAppsecret() + timestamp)
                    .toUpperCase();
            if (!Objects.equals(token, md5Hex)) {
                log.warn("token校验失败,参数：appid:{},appKey:{},timestamp:{},token:{}", appId, appKey, timestamp, token);
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return false;
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {

    }

}
